using namespace std;

#include<iostream>
#include<iomanip>
#include<vector>
#include<string>
#include<fstream>
#include<algorithm>
#include<map>
#include<set>
#include"BA2.h"

std::vector<string> cmdList;
std::vector<Indiv> sample;
std::map<string,int> popToindex;
std::map<int,string> indexTopop;
std::map<string,int> labelToindex;
std::map<int,string> indexTolabel;
std::set<string> labelSet;
std::set<string> popSet;
std::vector<long int> popCounts;
std::vector< vector< vector<long int> > > alleleCounts;
std::vector< set<string> > alleleSet;
std::vector< map<string,int> > alleleMap;
std::vector< map<int,string> > intToallele;
std::set<string> locusSet;
std::map<int,string> indexTolocus;
std::map<string,int> locusToindex;
double maxMigration=0.3;
bool infileOpen;

int main(int argc, char *argv[])
{
  std::vector< vector <vector <double> > > alleleFreqs;
  std::vector<double> popFstats;
  std::vector< vector <double> > migrationRates;
  std::vector<string> populationNames;
  std::string filename="junk";
  std::string ofilename="BA2.out";

  ofstream outfile;
  ofstream logfile;
  ifstream infile;
  ifstream batchfile;

  Parameters pvalues;
  string cmd;
  int command;
  bool endBA=false;
  bool useBatchFile=false;
  infileOpen=false;
  enum { quit=1, badcommand=0, scan=2, pset=3, help=4, printData=5, printAlleles=6, bat=7, bayesAss=8, simulate=9, ssettings=10, comment=11, interact=12 };

  string t1;
  outfile.open(pvalues.outfile.c_str());
  logfile.open(pvalues.logfile.c_str());

  if(argc>2)
    cout << "usage: BA2 [batch file]\n";
  else
    {
      if(argc==2)
	{
	  batchfile.open(argv[1]);
	  if(batchfile)
	    {
	      cout << " Executing commands from batch file: " << argv[1] << "\n" << endl;
	      useBatchFile=true;
	    }
	  else
	    {
	      cout << "Failed to open batch file: " << argv[1] << "\n";
	      exit(0);
	    }
	}
      PrintBanner();
      while(!endBA)
	{
	  if(useBatchFile==false)
	    {
	      cout << "BA>";
	      getline(cin,cmd);
	      if(cmd[0]!='#')
		while(cmd.find(";")==string::npos)
		  {
		    cout << "->";
		    getline(cin,t1);
		    cmd=cmd+t1;
		  }
	    }
	  if(useBatchFile==true)
	    {
	      if(!getline(batchfile,cmd)) exit(0);
	    }

	  if(cmd[0]!='#')
	    {
	      string::size_type pos=cmd.find(";");
	      cmd=cmd.substr(0,pos);
	      command=TranslateCommand(cmd);
	    }
	  else command=11;
	  switch(command)
	    {
	    case scan:
	      if(cmdList.size()>2)
		{
		  if(infileOpen)
		    infile.close();
		  infile.open(cmdList[2].c_str());
		  pvalues.fileFormat=cmdList[1];	    
		  if(infile)
		    {
		      infileOpen=true;
		      ReadData(infile,pvalues);
		      filename=cmdList[2];
		    }
		  else
		    cout << "Failed to open file: " << cmdList[2] << "\n";
		}
	      else
		{
		  cout << "Missing argument for scan!\n";
		}
	      break;
	    case quit:
	      endBA=1;
	      cout << "exiting BA2...\n";
	      break;
	    case badcommand:
	      cout << cmd << ": command not found\n";
	      break;
	    case pset:
	      if(SetParameters(pvalues)==1)
		{
		  outfile.close();
		  outfile.open(pvalues.outfile.c_str());
		}
	      else
	      if(SetParameters(pvalues)==2)
		{
		  logfile.close();
		  logfile.open(pvalues.logfile.c_str());
		}		
	      break;
	    case help:
	      PrintCommands();
	      break;
	    case printData:
	      if(infileOpen)
		PrintData(filename);
	      else
		cout << "Cannot execute printData (no input file).\n";
	      break;
	    case printAlleles:
	      if(infileOpen)
		PrintAlleleCounts(pvalues);
	      else
		cout << "Cannot execute printAlleles (no input file).\n";
	      break;
	    case bat:
	      if(infileOpen)
		if(pvalues.alist.size()>0)
		  {
		    Bat(pvalues);
		  }
		else
		  cout << "Cannot execute bat (alist is empty).\n";
	      else
		cout << "Cannot execute bat (no input file).\n";
	      break;
	    case bayesAss:
	      if(infileOpen)
		{
		  BayesAss BA;	      
		  BA.BayesAssMCMC(pvalues,outfile,logfile);
		}
	      else
		cout << "Cannot execute BayesAss (no input file).\n";
	      break;
	    case ssettings:
	      sset();
	      break; 
	    case comment:
	      cout << cmd << "\n";
	      break;
	    case interact:
	      useBatchFile=false;
	      break;
	    case simulate:
	      Simulate sim;
	      sim.simulateSample();
	      sim.PrintAlleleFreqs();
	      sim.PrintMigrantAncestries();
	      break;
	    }
	    }
    } 
}
